var GlobalErrorListener = require('./GlobalErrorListener');
var Observer = function () {
};
Observer.prototype = Object.create(Object.prototype, {
    constructor: {
        value: Observer,
        writable: true,
        configurable: true
    }
});
Observer.create = function (e) {
    var t = new Observer();
    t._cb = e;
    t._noSubtreeCb = function (t) {
        t.target === this && e.call(this, t);
    };
    t._binded = [];
    return t;
};
Observer.prototype.observe = function (e, t) {
    var i = 0;
    var a = (t = t || {}).subtree ? this._cb : this._noSubtreeCb;
    if (t.properties) {
        e.__propObservers || (e.__propObservers = GlobalErrorListener.create('Observer Callback'));
        this._binded.push({
            funcArr: e.__propObservers,
            id: e.__propObservers.add(a),
            subtree: t.subtree ? e : null
        });
        i++;
    };
    if (t.childList) {
        e.__childObservers || (e.__childObservers = GlobalErrorListener.create('Observer Callback'));
        this._binded.push({
            funcArr: e.__childObservers,
            id: e.__childObservers.add(a),
            subtree: t.subtree ? e : null
        });
        i++;
    };
    if (t.characterData) {
        e.__textObservers || (e.__textObservers = GlobalErrorListener.create('Observer Callback'));
        this._binded.push({
            funcArr: e.__textObservers,
            id: e.__textObservers.add(a),
            subtree: t.subtree ? e : null
        });
        i++;
    };
    t.subtree && r(e, i);
    t.attachStatus && (e.__attachedObservers || (e.__attachedObservers = GlobalErrorListener.create('Observer Callback')), this._binded.push({
        funcArr: e.__attachedObservers,
        id: e.__attachedObservers.add(a),
        subtree: null
    }));
};
Observer.prototype.disconnect = function () {
    var e = this._binded;
    for (var t = 0; t < e.length; t++) {
        var i = e[t];
        i.funcArr.remove(i.id);
        i.subtree && r(i.subtree, -1);
    }
    this._binded = [];
};
var r = Observer._updateSubtreeCaches = function (e, t) {
    e.__subtreeObserversCount += t;
    var i = e.childNodes;
    if (i)
        for (var n = 0; n < i.length; n++)
            r(i[n], t);
};
Observer._callObservers = function (e, t, i) {
    do {
        e[t] && e[t].call(e, [i]);
        e = e.parentNode;
    } while (e && e.__subtreeObserversCount);
};
Observer._callSingleObserver = function (e, t, i) {
    e[t] && e[t].call(e, [i]);
};
module.exports = Observer;
